#pragma once
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>

#include "base_util/log_lite.h"
#include "pdmodel/src/pdmodel_struct.h"
#include "common/base_struct.h"

using namespace paddle_infer;
using namespace common;

namespace algo {

class BaseAlgo;

enum WeatherType {
  weather_fog1,      // 小雾
  weather_fog2,      // 大雾
  weather_norm,     // 正常
  weather_rain1,     // 小雨
  weather_rain2,     // 大雨
  weather_snow1,     // 堆雪
  weather_snow2,     // 小雪
  weather_snow3,     // 大雪
};

typedef struct CameraCtrolInfo {
  CameraCtrolInfo(): ok(false), p(0), t(0), z(0) {}
  CameraCtrolInfo(int p, int t, int z):
                  p(p), t(t), z(z), ok(true) {}
  CameraCtrolInfo(const CameraCtrolInfo& ci) {
    *this = operator=(ci);
  }
  CameraCtrolInfo& operator=(const CameraCtrolInfo& ci) {
    if (this == &ci) { return *this; }
    this->minL = ci.minL;
    this->maxR = ci.maxR;
    this->minT = ci.minT;
    this->maxB = ci.maxB;
    this->minZ = ci.minZ;
    this->maxZ = ci.maxZ;
    this->p = ci.p;
    this->t = ci.t;
    this->z = ci.z;
    this->ok = ci.ok;
    this->mapPath = ci.mapPath;
    this->lon = ci.lon;
    this->lan = ci.lan;
    this->height = ci.height;
    this->azimuthDiff = ci.azimuthDiff;
    return *this;
  }
  bool operator==(const CameraCtrolInfo& ci) {
    if (this == &ci) { return true; }
    return minL == ci.minL && maxR == ci.maxR && minT == ci.minT && maxB == ci.maxB && \
           minZ == ci.minZ && maxZ == ci.maxZ && p == ci.p && t == ci.t && \
           z == ci.z && mapPath == ci.mapPath && lon == ci.lon && lan == ci.lan && \
           height == ci.height && azimuthDiff == ci.azimuthDiff;
  }
  int minL;                              // 最小x
  int maxR;
  int minT;
  int maxB;                              // 最大y
  int minZ;
  int maxZ;

  int p;
  int t;
  int z;
  bool ok;

  // 地图信息
  std::string mapPath;
  int64 lon;
  int64 lan;
  int height;
  float azimuthDiff;
}CameraCtrolInfo_;

typedef struct AlgoModule {

  std::string type;                       // 模块类型
  int uploadVideo;                        // 上传报警视频
  int analysisValue;      
  int analysisInterval;                   // 分析间隔
  std::vector<cv::Point> analysisPoint;

  int detectInterval;                     // 检测间隔
  std::vector<cv::Point> detectRegion;    // 检测区域

  int64 start_time;                       // 毫秒
}AlgoModule_;


typedef struct CameraModule {
  AlgoModule param;                       // 大算法
  std::vector<AlgoModule> params;         // 小算法

  std::shared_ptr<BaseAlgo> algo;            // 算法模块
  int64 start_time;                       // 毫秒
}CameraModule_;


typedef struct CameraInfo : public CameraInfoBase {
  CameraInfo(): CameraInfoBase(), rec_region(cv::Rect()), delay_seconds(0) {}
  CameraInfo(const CameraInfo& ci) {
    *this = operator=(ci);
  }
  CameraInfo& operator=(const CameraInfo& ci) {
    if (this == &ci) { return *this; }
    CameraInfoBase::operator=(ci);
    rec_region = ci.rec_region;
    delay_seconds = ci.delay_seconds;
    return *this;
  }
  bool operator==(const CameraInfo& ci) {
    if (this == &ci) { return true; }
    spdlog::get("logger")->info("CameraInfoBase::operator==(ci):{}", CameraInfoBase::operator==(ci));
    return CameraInfoBase::operator==(ci) && this->rec_region == ci.rec_region && this->delay_seconds == ci.delay_seconds;
  }
  cv::Rect rec_region;              // 识别区域
  int delay_seconds;              // 上传间隔
}CameraInfo_;

typedef struct CameraGroup : public CameraGroupBase {
  CameraGroup(): CameraGroupBase() {
    cam_ifo = CameraInfo();
    // cam_mdl = CameraModule();
    // cam_ctl_ifo = CameraCtrolInfo();
  }
  CameraGroup(const CameraGroup& ci) {
    *this = operator=(ci);
  }
  CameraGroup& operator=(const CameraGroup& ci) {
    if (this == &ci) { return *this; }
    CameraGroupBase::operator=(ci);
    this->cam_ifo = ci.cam_ifo;
    // this->cam_ctl_ifo = ci.cam_ctl_ifo;
    // this->cam_mdl = ci.cam_mdl;
    return *this;
  }
  bool operator==(const CameraGroup& ci) {
    if (this == &ci) { return true; }
    return this->cam_ifo == ci.cam_ifo;
  }
  CameraInfo cam_ifo;
  // CameraCtrolInfo cam_ctl_ifo;
  // CameraModule cam_mdl;
};

typedef struct PostInfo : public PostInfoBase {
  PostInfo(): PostInfoBase() {}
  PostInfo( int64 start_time, int64 end_time, int64 time, std::string algo_type, 
            int alarm, std::string img_path, std::string alarm_info, int try_cnt):
            PostInfoBase(start_time, end_time, time, algo_type, alarm, img_path, alarm_info, try_cnt) { }
  PostInfo(const PostInfo &pi) {
    *this = operator=(pi);
  }
  PostInfo& operator=(const PostInfo& pi) {
    if (this == &pi) { return *this; }
    PostInfoBase::operator=(pi);
    video_path = pi.video_path;
    eventId = pi.eventId;
    cam_grp = pi.cam_grp;
    return *this;
  }

  std::string video_path;         // sideslope
  std::string eventId;
  CameraGroup* cam_grp;
}PostInfo_;

}   // namespace smartbox
